// Copyright Leonid Shlyapnikov 2010
// Distributed under the GNU Lesser General Public License http://www.gnu.org/licenses/lgpl.html
//    author: Leonid Shlyapnikov, created on: Feb 1, 2010

#include <boost/test/test_tools.hpp>
#include <cstring>
#include <stdexcept>

#include "../../main/fixparser/String.h"
#include "../../main/fixparser/MemoryArea.h"
#include "../../main/fixparser/Field.h"
#include "../../main/fixparser/log.h"
#include "../../main/fixparser/util.h"

void String_assign() {
    using fixparser::MemoryArea;
    using fixparser::String;
    using fixparser::static_strlen;

    // GIVEN
    MemoryArea ma(1024);
    const char cstr[] = "test_string";
    String str(&ma);

    // WHEN
    str.assign(cstr, static_strlen(cstr));

    // THEN
    BOOST_CHECK_EQUAL(11, static_strlen(cstr));
    BOOST_CHECK_EQUAL(ma.size(), static_strlen(cstr) + 1);
    BOOST_CHECK_EQUAL(str.length(), static_strlen(cstr));
    BOOST_CHECK_EQUAL(str.length(), 11);
    BOOST_CHECK_EQUAL(str.c_str(), cstr);
}

void String_MemoryAreaAllocateAssign() {
    using fixparser::MemoryArea;
    using fixparser::String;
    using fixparser::static_strlen;

    // GIVEN
    MemoryArea ma(1024);
    const char cstr[] = "test_string";
    String* str = ma.create<String>();

    // WHEN
    str->assign(cstr, static_strlen(cstr));

    // THEN
    BOOST_CHECK_EQUAL(ma.size(), static_strlen(cstr) + 1 + sizeof(String));
    BOOST_CHECK_EQUAL(str->length(), static_strlen(cstr));
    BOOST_CHECK_EQUAL(str->length(), 11);
    BOOST_CHECK_EQUAL(str->c_str(), cstr);
}

void String_assign2() {
    using fixparser::MemoryArea;
    using fixparser::String;
    using std::strlen;
    using fixparser::static_strncpy;

    // GIVEN
    MemoryArea ma(1024);
    char* cstr = ma.allocate<char>(128);
    static_strncpy(cstr, "test_string");
    String str(&ma);

    // WHEN
    str.assign(cstr, strlen(cstr));

    // THEN
    BOOST_CHECK_EQUAL(ma.size(), 128);
    BOOST_CHECK_EQUAL(str.c_str(), cstr);
    BOOST_CHECK_EQUAL(str.length(), strlen(cstr));
    BOOST_CHECK_EQUAL(reinterpret_cast<int64_t>(str.c_str()), reinterpret_cast<int64_t>(cstr));
}

void String_reassign() {
    using fixparser::MemoryArea;
    using fixparser::String;
    using fixparser::static_strlen;

    // GIVEN
    MemoryArea ma(1024);
    const char cstr0[] = "test_string0";
    const char cstr1[] = "test_string_01";
    String str(&ma);
    str.assign(cstr0, static_strlen(cstr0));

    // WHEN
    str.assign(cstr1, static_strlen(cstr1));

    // THEN
    BOOST_CHECK_EQUAL(ma.size(), static_strlen(cstr0) + 1 + static_strlen(cstr1) + 1);
    BOOST_CHECK_EQUAL(str.c_str(), cstr1);
    BOOST_CHECK_EQUAL(str.length(), static_strlen(cstr1));
}

void String_reassign2() {
    using fixparser::MemoryArea;
    using fixparser::String;
    using std::strlen;
    using fixparser::static_strncpy;

    // GIVEN
    MemoryArea ma(1024);
    char* cstr0 = ma.allocate<char>(128);
    static_strncpy(cstr0, "test_string0");
    char* cstr1 = ma.allocate<char>(128);
    static_strncpy(cstr1, "test_string1");
    String str(&ma);
    str.assign(cstr0, strlen(cstr0));

    // WHEN
    str.assign(cstr1, strlen(cstr1));

    // THEN
    BOOST_CHECK_EQUAL(ma.size(), 128 * 2);
    BOOST_CHECK_EQUAL(str.c_str(), cstr1);
    BOOST_CHECK_EQUAL(str.length(), strlen(cstr1));
    BOOST_CHECK_EQUAL(reinterpret_cast<int64_t>(str.c_str()), reinterpret_cast<int64_t>(cstr1));
}

/*
void String_assignTagId() {
    using fixparser::MemoryArea;
    using fixparser::String;

    // GIVEN
    MemoryArea ma(1024);
    int expectedMaSize = 0;
    String str(&ma);
    BOOST_CHECK_EQUAL(ma.size(), expectedMaSize);

    // WHEN 1
    str.assignTagId(1);

    // THEN 1
    expectedMaSize += 2; // '1' and terminating zero
    BOOST_CHECK_EQUAL(ma.size(), expectedMaSize);
    BOOST_CHECK_EQUAL(str.c_str(), "1");

    // WHEN 2
    str.assignTagId(50);

    // THEN 2
    expectedMaSize += 3;
    BOOST_CHECK_EQUAL(ma.size(), expectedMaSize);
    BOOST_CHECK_EQUAL(str.c_str(), "50");

    // WHEN 3
    str.assignTagId(500);

    // THEN 3
    expectedMaSize += 4;
    BOOST_CHECK_EQUAL(ma.size(), expectedMaSize);
    BOOST_CHECK_EQUAL(str.c_str(), "500");

    // WHEN 4
    str.assignTagId(5000);

    // THEN 4
    expectedMaSize += 5;
    BOOST_CHECK_EQUAL(ma.size(), expectedMaSize);
    BOOST_CHECK_EQUAL(str.c_str(), "5000");

    // WHEN-THEN 5
    BOOST_CHECK_THROW(str.assignTagId(50000), std::invalid_argument);
}
*/

void String_assign_std_string() {
    using fixparser::MemoryArea;
    using std::strlen;
    using fixparser::static_strncpy;

    // GIVEN
    MemoryArea ma(1024);
    fixparser::String* fixparserString = ma.create<fixparser::String>();
    const size_t initialMaSize = ma.size();
    BOOST_CHECK_EQUAL(ma.size(), sizeof(fixparser::String));
    std::string stdstring("std string");
    const size_t stdstringSize = stdstring.size();

    // THEN
    fixparserString->assign(stdstring);

    // WHEN
    BOOST_CHECK_EQUAL(ma.size(), (initialMaSize + stdstringSize + 1));
    BOOST_CHECK_EQUAL(fixparserString->c_str(), stdstring);
}
